package com.ksyun.ks3.services.handler;

import java.io.ByteArrayInputStream;
import java.io.IOException;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import com.ksyun.ks3.exception.Ks3ClientException;
import com.ksyun.ks3.exception.Ks3ServiceException;
import com.ksyun.ks3.model.Owner;
import com.ksyun.ks3.model.acl.AccessControlList;
import com.ksyun.ks3.model.acl.AccessControlPolicy;
import com.ksyun.ks3.model.acl.Grant;
import com.ksyun.ks3.model.acl.Grantee;
import com.ksyun.ks3.model.acl.GranteeEmail;
import com.ksyun.ks3.model.acl.GranteeId;
import com.ksyun.ks3.model.acl.GranteeUri;
import com.ksyun.ks3.model.acl.Permission;
import com.ksyun.ks3.model.result.GetBucketACLResult;
import com.ksyun.ks3.services.request.GetBucketACLRequest;
import com.ksyun.ks3.services.request.Ks3HttpRequest;
import com.ksyun.ks3.util.ResponseUtils;

import okhttp3.Headers;

public abstract class GetBucketACLResponseHandler extends Ks3HttpResponseHandler {

    public abstract void onFailure(GetBucketACLRequest request, Ks3ClientException clientException, Ks3ServiceException serviceException);

    public abstract void onSuccess(GetBucketACLRequest request, GetBucketACLResult result);

    @Override
    public final void onSuccess(Ks3HttpRequest request, int statusCode, Headers responseHeaders, byte[] response) {
        GetBucketACLResult result = new GetBucketACLResult();
        result.setStatusCode(statusCode);
        result.setHeaders(ResponseUtils.parseResponseHeaders(responseHeaders));
        result.setAccessControlPolicy(parseXml(response));
        this.onSuccess((GetBucketACLRequest) request, result);
    }

    @Override
    public final void onFailure(Ks3HttpRequest request, Ks3ClientException clientException, Ks3ServiceException serviceException) {
        this.onFailure((GetBucketACLRequest) request, clientException, serviceException);
    }

    @Override
    public final void onProgress(long bytesWritten, long totalSize) {
    }

    @Override
    public final void onStart() {
    }

    @Override
    public final void onFinish() {
    }

    @Override
    public final void onCancel() {
    }

    private AccessControlPolicy parseXml(byte[] response) {
        XmlPullParserFactory factory;
        Grantee grantee = null;
        Grant grant = null;
        AccessControlList accessControlList = null;
        Owner owner = null;
        Permission permission = null;
        AccessControlPolicy accessControlPolicy = null;
        try {
            factory = XmlPullParserFactory.newInstance();
            XmlPullParser parse = factory.newPullParser();
            parse.setInput(new ByteArrayInputStream(response), "UTF-8");
            int eventType = parse.getEventType();
            while (XmlPullParser.END_DOCUMENT != eventType) {
                String nodeName = parse.getName();
                switch (eventType) {
                    case XmlPullParser.START_DOCUMENT:
                        break;
                    case XmlPullParser.END_DOCUMENT:
                        break;
                    case XmlPullParser.START_TAG:
                        if ("AccessControlPolicy".equalsIgnoreCase(nodeName)) {
                            accessControlPolicy = new AccessControlPolicy();
                        }
                        if ("Owner".equalsIgnoreCase(nodeName)) {
                            owner = new Owner();
                            parse.next();
                            nodeName = parse.getName();
                            if ("ID".equalsIgnoreCase(nodeName)) {
                                owner.setId(parse.nextText());
                            }
                            parse.next();
                            nodeName = parse.getName();
                            if ("DisplayName".equalsIgnoreCase(nodeName)) {
                                owner.setDisplayName(parse.nextText());
                            }
                        }

                        if (nodeName.equalsIgnoreCase("AccessControlList")) {
                            accessControlList = new AccessControlList();
                        }

                        if ("Grant".equalsIgnoreCase(nodeName)) {
                            grant = new Grant();
                        }
                        if ("Grantee".equalsIgnoreCase(nodeName)) {
                            parse.next();
                            nodeName = parse.getName();
                            if ("EmailAddress".equalsIgnoreCase(nodeName)) {
                                grantee = new GranteeEmail();
                                grantee.setIdentifier(parse.nextText());
                            } else if ("URI".equalsIgnoreCase(nodeName)) {
                                grantee = GranteeUri.parse(parse.nextText());
                            } else if ("ID".equalsIgnoreCase(nodeName)) {
                                grantee = new GranteeId();
                                grantee.setIdentifier(parse.nextText());
                            }
                        }
                        if ("Permission".equalsIgnoreCase(nodeName)) {
                            permission = Permission.getInstance(parse.nextText());
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        if (nodeName.equalsIgnoreCase("AccessControlList")) {
                        }
                        if ("Grant".equalsIgnoreCase(nodeName)) {
                            grant.setGrantee(grantee);
                            grant.setPermission(permission);
                            accessControlList.addGrant(grant);
                        }
                        if ("AccessControlPolicy".equalsIgnoreCase(nodeName)) {
                            accessControlPolicy.setAccessControlList(accessControlList);
                            accessControlPolicy.setOwner(owner);
                        }
                        break;
                    case XmlPullParser.TEXT:

                        break;
                    default:
                        break;
                }
                eventType = parse.next();
            }
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return accessControlPolicy;
    }
}
